﻿using System;
using System.Collections.ObjectModel;
using System.Xml.Serialization;
using EpiNEXT.Foundation;

namespace EpiNEXT.Services
{
    //[Serializable()]
    public class CodeList : ObservableObject
    {
        #region Members
        private string _name = String.Empty;
        private CodeListMode _codeListMode = CodeListMode.Basic;
        private string _codeListModeString = String.Empty;
        #endregion // Members

        #region Properties
        [XmlElement("Mode")]
        public string ModeStr
        {
            get
            {
                return this._codeListModeString;
            }
            set
            {
                if (!(_codeListModeString.Equals(value)))
                {
                    this._codeListModeString = value;
                    switch (ModeStr)
                    {
                        case "Coded":
                            Mode = CodeListMode.Coded;
                            break;
                        case "CodedCascadeFromSource":
                            Mode = CodeListMode.CodedCascadeFromSource;
                            break;
                        case "CodedCascadeToDestination":
                            Mode = CodeListMode.CodedCascadeToDestination;
                            break;
                        case "Basic":
                        default:
                            Mode = CodeListMode.Basic;
                            break;
                    }
                }
            }
        }

        [XmlIgnore]
        public CodeListMode Mode
        {
            get
            {
                return this._codeListMode;
            }
            set
            {
                if (_codeListMode != value)
                {
                    this._codeListMode = value;
                    switch (Mode)
                    {
                        case CodeListMode.Coded:
                            ModeStr = "Coded";
                            break;
                        case CodeListMode.CodedCascadeFromSource:
                            ModeStr = "CodedCascadeFromSource";
                            break;
                        case CodeListMode.CodedCascadeToDestination:
                            ModeStr = "CodedCascadeToDestination";
                            break;
                        case CodeListMode.Basic:
                        default:
                            ModeStr = "Basic";
                            break;
                    }
                    RaisePropertyChanged("Mode");
                }
            }
        }

        [XmlElement("Concatenate")]
        public bool Concatenate { get; set; }

        [XmlElement("Separator")]
        public string Separator { get; set; }

        [XmlElement("Id")]
        public Guid Id { get; set; }

        /// <summary>
        /// The list of values
        /// </summary>
        [XmlArray("ListValues")]
        [XmlArrayItem("ListValue", typeof(CodeListValue))]
        public ObservableCollection<CodeListValue> CodeListValues { get; set; }

        [XmlElement("Name")]
        public string Name
        {
            get
            {
                return this._name;
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                {
                    throw new InvalidOperationException("List name cannot be blank.");
                }
                else if (value.Length > 64)
                {
                    throw new InvalidOperationException("List name cannot exceed 64 characters.");
                }
                else if (!System.Text.RegularExpressions.Regex.IsMatch(value, @"\w"))
                {
                    throw new InvalidOperationException("List name must include only letters, numbers, and underscores.");
                }
                else
                {
                    double firstChar = -1;
                    bool success = double.TryParse(value[0].ToString(), out firstChar);
                    if (success)
                    {
                        throw new InvalidOperationException("List name may not start with a digit.");
                    }

                    this._name = value;
                }
            }
        }
        #endregion // Properties

        #region Constructors
        public CodeList()
        {
            CodeListValues = new ObservableCollection<CodeListValue>();
            Id = Guid.NewGuid();
            Mode = CodeListMode.Basic;
            Concatenate = false;
        }
        #endregion // Constructors

        #region Methods
        public override string ToString()
        {
            return this.Name;
        }
        #endregion // Methods
    }
}
